#ifndef __COMM_HPP__
#define __COMM_HPP_
// #ifndef, #define, 和 #endif 是预处理指令，它们用于防止头文件的多重包含
/*#ifndef __COMM_HPP__: 这是一个预处理条件。它检查是否已定义了名为__COMM_HPP__的宏。如果没有定义，那么随后的代码会被包括在内。
#define __COMM_HPP__: 这定义了一个名为__COMM_HPP__的宏。这通常意味着这个头文件已经被包含进来了。
#endif: 这标志着#ifndef条件的结束。*/ 

#include<iostream>
#include<cstdlib>
#include<string>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include"log.hpp"
#include <string.h>
using namespace std;

const int size = 4096;
//共享内存的大小一般建议是4096的整数倍。
//4097，实际上操作系统给你的是4096*2的大小。但你只能用4097的空间大小，多余的用不了。
const string pathname = "/home/hcm";
const int proj_id = 0x6666;
Log log;

key_t GetKey()//首先获得键值
{
    //在Linux中，ftok是一个用于生成唯一的键值（key）的函数，
    //通常用于创建和访问共享内存、消息队列和信号量等进程间通信(IPC)对象。ftok函数根据给定的路径名和项目ID生成一个唯一的键值。
    //key_t ftok(const char *pathname, int proj_id);
    /*pathname：一个以null结尾的字符串，表示路径名。这通常是一个已存在的文件或目录的路径。
    proj_id：一个整数，表示项目ID。这个值通常用于区分不同的共享内存、消息队列和信号量对象。
    返回值：如果成功，ftok返回一个唯一的键值。如果失败，返回-1并设置errno以指示错误。*/
    key_t k = ftok(pathname.c_str(),proj_id);
    if(k < 0)
    {
        log(Fatal,"ftok error:%s",strerror(errno));
        
        exit(1);
    }
    log(Info,"ftok sucess,key is %d",k);

    return k;
}

int GetShareMemHelper(int flag)//其次获得共享内存块
{
    key_t k = GetKey();
    //int shmget(key_t key, size_t size, int shmflg);
    //shmget 是 Linux 系统中用于创建或访问共享内存段的系统调用。通过 shmget，
    //你可以获得一个共享内存标识符，这个标识符可以用于 shmat（将共享内存连接到进程的地址空间）和 shmdt（从进程地址空间分离共享内存）等系统调用。
    //key：共享内存的唯一键值。这通常是通过 ftok 函数生成的。
    //size：以字节为单位的共享内存大小。如果这个值是 0，并且所请求的共享内存段已经存在，
    //那么系统会返回该共享内存段的标识符，而不会创建新的共享内存段。
    //shmflg：共享内存的访问权限和创建标志。这可以是 IPC_CREAT（如果不存在则创建）、
    //IPC_EXCL（与 IPC_CREAT 一同使用，如果共享内存已经存在则返回错误）、以及各种访问权限的组合（如 0666 表示所有用户都有读写权限）。
    //返回值：如果成功，shmget 返回一个共享内存标识符（非负整数）。如果失败，返回 -1 并设置 errno 以指示错误。
    int shmid = shmget(k,size,flag);
    if(shmid <0)
    {
        log(Fatal,"create share memory error: %s",strerror(errno));
        exit(2);
    }
    log(Info,"create share memory success,shmid:%d",shmid);
    return shmid;
}

int CreateShm()
{
    return GetShareMemHelper(IPC_CREAT|IPC_EXCL|0666);//IPC_CREAT|IPC_EXCL如果你获取的内存不存在就创建，存在就出错哦，|0666是给共享内存设置权限
    //因为Linux下一切皆文件这个思想，故共享内存这个“文件”也有权限哦。
}

int GetShm()
{
    return GetShareMemHelper(IPC_CREAT);//IPC_CREAT单独，如果你申请的内存不存在就创建，存在就获取并返回。
}



#endif
